package com.smart.web.controller;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.smart.dao.Page;
import com.smart.dao.PageRequest;
import com.smart.model.RawData;
import com.smart.model.RawDataCond;
import com.smart.util.DateUtil;
import com.smart.util.FileUtil;
import com.smart.util.ReflectionUtils;

import jodd.util.StringUtil;

@Controller
public class RawDataController extends BaseController {
	@RequestMapping(value = "admin/rawData/list")
	public String listRawData(PageRequest pageRequest, Model model){
		Page<RawData> page = rawDataService.findAll(pageRequest);
		model.addAttribute("page", page);
		return "admin/rawData/list";
	}
	
	@RequestMapping(value = "admin/rawData/edit", method=RequestMethod.GET)
	public String preEditRawData(Long id, Model model) {
		if(id!=null){
			RawData rawData = rawDataService.findOne(id);
			model.addAttribute("obj", rawData);
		}
		return "admin/rawData/edit";
	}
	
	@RequestMapping(value = "admin/rawData/upload", method=RequestMethod.GET)
	public String preUpload() {
		return "admin/rawData/upload";
	}
	
	public static void main(String[] args) {
		System.out.println("aa   bb cc".replaceAll(" ", ""));
		System.out.println("1,2,3,4".matches("^[0-9,]*$"));
	}
	
	@RequestMapping(value = "admin/rawData/upload", method=RequestMethod.POST)
	public String uploadAndRemoveDuplicateAndDownload(final String channel, String columns, String ignoreFirstRow, MultipartFile file, 
					HttpServletResponse response, Model model) 
				throws IOException {
		final String batchId = DateUtil.format("yyyyMMddhhmmss", new Date());
		if(StringUtil.isEmpty(channel)) {
			super.setErrorMsg(model, "渠道不能为空");
			return "admin/rawData/upload"; 
		}
		if(StringUtil.isEmpty(columns)) {
			super.setErrorMsg(model, "有效数据的列编号不能为空");
			return "admin/rawData/upload"; 
		}
		columns = columns.replaceAll(" ", "");
		if(!columns.matches("^[0-9,]*$")) {
			super.setErrorMsg(model, "有效列只能是数字加英文逗号");
			return "admin/rawData/upload"; 
		}
		if(file.isEmpty()) {
			super.setErrorMsg(model, "上传文件为空, 无效");
			return "admin/rawData/upload"; 
		}
		final String origFileName = file.getOriginalFilename();
		String ext = FileUtil.getFileNameExtension(origFileName).toLowerCase();
		if(!"xls".equals(ext) && !"xlsx".equals(ext)) {
			super.setErrorMsg(model, "上传文件不是Excel, 无效");
			return "admin/rawData/upload"; 
		}
		String[] cols = columns.split(",");
		final int[] colIndexes = new int[cols.length];
		for(int i=0; i<cols.length; i++) {
			colIndexes[i] = Integer.parseInt(cols[i])-1;
		}
		
		final AtomicInteger dupCount = new AtomicInteger(0);
		
		OutputStream out = response.getOutputStream();
		response.setContentType("application/octet-stream");
		response.addHeader("Content-Disposition", "attachment;filename=no_dup_"  + origFileName);  

		ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX, false);
		final List<List<String>> outData = new ArrayList<List<String>>();
		ExcelReader excelReader = new ExcelReader(file.getInputStream(), ExcelTypeEnum.XLSX, null, new AnalysisEventListener<ArrayList<String>>() {
			@Override
			public void invoke(ArrayList<String> row, AnalysisContext context) {
				RawData data = new RawData();
				data.setBatchId(batchId);
				data.setChannel(channel);
				data.setOrigFileName(origFileName);
				for(int i=0; i<colIndexes.length; i++) {
					String col = row.get(colIndexes[i]);
					ReflectionUtils.invokeSetterMethod(data, "c" + (i+1), col);
				}
				
				boolean notDup = checkDuplication(data.getC1(), data.getChannel());
				if(notDup) {
					rawDataService.save(data);
					outData.add(row);
				}
				else {
					System.out.println("重复数据条数:" + dupCount.incrementAndGet());
				}
				
			}

			@Override
			public void doAfterAllAnalysed(AnalysisContext context) {
				
			}
        });
		try {
			excelReader.read();
			Sheet sheet1 = new Sheet(1, 0);
			sheet1.setSheetName("去重后的数据");
			writer.write0(outData, sheet1);
			writer.finish();
			out.flush();
			if(dupCount.intValue()!=0) {
				super.setErrorMsg(model, "刚才上传的文件中和历史重复的数据有" + dupCount.intValue() + "条");
			}
			else {
				super.setSuccessMsg(model);
			}
		}
		catch(Exception e) {
			
		}
		return "admin/rawData/upload";
	}
	
	@RequestMapping(value = "admin/rawData/upload1", method=RequestMethod.POST)
	public String upload(final String channel, String columns, String ignoreFirstRow, MultipartFile file, Model model) throws IOException {
		final String batchId = DateUtil.format("yyyyMMddhhmmss", new Date());
		if(StringUtil.isEmpty(channel)) {
			super.setErrorMsg(model, "渠道不能为空");
			return "admin/rawData/upload"; 
		}
		if(StringUtil.isEmpty(columns)) {
			super.setErrorMsg(model, "有效数据的列编号不能为空");
			return "admin/rawData/upload"; 
		}
		columns = columns.replaceAll(" ", "");
		if(!columns.matches("^[0-9,]*$")) {
			super.setErrorMsg(model, "有效列只能是数字加英文逗号");
			return "admin/rawData/upload"; 
		}
		if(file.isEmpty()) {
			super.setErrorMsg(model, "上传文件为空, 无效");
			return "admin/rawData/upload"; 
		}
		final String origFileName = file.getOriginalFilename();
		String ext = FileUtil.getFileNameExtension(origFileName).toLowerCase();
		if(!"xls".equals(ext) && !"xlsx".equals(ext)) {
			super.setErrorMsg(model, "上传文件不是Excel, 无效");
			return "admin/rawData/upload"; 
		}
		String[] cols = columns.split(",");
		final int[] colIndexes = new int[cols.length];
		for(int i=0; i<cols.length; i++) {
			colIndexes[i] = Integer.parseInt(cols[i])-1;
		}
		
		final AtomicInteger dupCount = new AtomicInteger(0);
		ExcelReader excelReader = new ExcelReader(file.getInputStream(), ExcelTypeEnum.XLSX, null, new AnalysisEventListener<ArrayList<String>>() {
			@Override
			public void invoke(ArrayList<String> row, AnalysisContext context) {
				RawData data = new RawData();
				data.setBatchId(batchId);
				data.setChannel(channel);
				data.setOrigFileName(origFileName);
				for(int i=0; i<colIndexes.length; i++) {
					String col = row.get(colIndexes[i]);
					ReflectionUtils.invokeSetterMethod(data, "c" + (i+1), col);
				}
				
				boolean notDup = checkDuplication(data.getC1(), data.getChannel());
				if(notDup) {
					rawDataService.save(data);
				}
				else {
					System.out.println("重复数据条数:" + dupCount.incrementAndGet());
				}
				
			}

			@Override
			public void doAfterAllAnalysed(AnalysisContext context) {
				
			}
        });
		try {
			excelReader.read();
			if(dupCount.intValue()!=0) {
				super.setErrorMsg(model, "刚才上传的文件中和历史重复的数据有" + dupCount.intValue() + "条");
			}
			else {
				super.setSuccessMsg(model);
			}
		}
		catch(Exception e) {
			
		}
		return "admin/rawData/upload";
	}
	
	private boolean checkDuplication(String mobile, String channel) {
		RawDataCond cond = new RawDataCond();
		cond.setC1(mobile);
		cond.setChannel(channel);
		long count = rawDataService.count(cond);
		if(count<=0) {
			return true;
		}
		return false;
	}
	
}
